package cn.iocoder.yudao.module.iot.gateway.codec.alink;

import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.gateway.codec.IotDeviceMessageCodec;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * 阿里云 Alink {@link IotDeviceMessage} 的编解码器
 *
 * @author 芋道源码
 */
@Component
public class IotAlinkDeviceMessageCodec implements IotDeviceMessageCodec {

    private static final String TYPE = "Alink";

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private static class AlinkMessage {

        public static final String VERSION_1 = "1.0";

        /**
         * 消息 ID，且每个消息 ID 在当前设备具有唯一性
         */
        private String id;

        /**
         * 版本号
         */
        private String version;

        /**
         * 请求方法
         */
        private String method;

        /**
         * 请求参数
         */
        private Object params;

        /**
         * 响应结果
         */
        private Object data;
        /**
         * 响应错误码
         */
        private Integer code;
        /**
         * 响应提示
         *
         * 特殊：这里阿里云是 message，为了保持和项目的 {@link CommonResult#getMsg()} 一致。
         */
        private String msg;

    }

    @Override
    public String type() {
        return TYPE;
    }

    @Override
    public byte[] encode(IotDeviceMessage message) {
        AlinkMessage alinkMessage = new AlinkMessage(message.getRequestId(), AlinkMessage.VERSION_1,
                message.getMethod(), message.getParams(), message.getData(), message.getCode(), message.getMsg());
        return JsonUtils.toJsonByte(alinkMessage);
    }

    @Override
    @SuppressWarnings("DataFlowIssue")
    public IotDeviceMessage decode(byte[] bytes) {
        try {
            AlinkMessage alinkMessage = JsonUtils.parseObject(bytes, AlinkMessage.class);
            Assert.notNull(alinkMessage, "消息不能为空");
            Assert.equals(alinkMessage.getVersion(), AlinkMessage.VERSION_1, "消息版本号必须是 1.0");
            
            // 调试日志：打印原始params类型
            System.out.println("AlinkMessage params类型: " + (alinkMessage.getParams() == null ? "null" : alinkMessage.getParams().getClass().getName()));
            System.out.println("AlinkMessage params内容: " + alinkMessage.getParams());
            
            return IotDeviceMessage.of(alinkMessage.getId(), alinkMessage.getMethod(), alinkMessage.getParams(),
                    alinkMessage.getData(), alinkMessage.getCode(), alinkMessage.getMsg());
        } catch (Exception e) {
            // 尝试修复常见的JSON格式问题
            String jsonStr = new String(bytes);
            String fixedJson = fixCommonJsonIssues(jsonStr);
            
            try {
                AlinkMessage alinkMessage = JsonUtils.parseObject(fixedJson.getBytes(), AlinkMessage.class);
                Assert.notNull(alinkMessage, "修复后的消息不能为空");
                Assert.equals(alinkMessage.getVersion(), AlinkMessage.VERSION_1, "消息版本号必须是 1.0");
                
                System.out.println("JSON修复成功，原始JSON: " + jsonStr);
                System.out.println("修复后JSON: " + fixedJson);
                
                return IotDeviceMessage.of(alinkMessage.getId(), alinkMessage.getMethod(), alinkMessage.getParams(),
                        alinkMessage.getData(), alinkMessage.getCode(), alinkMessage.getMsg());
            } catch (Exception e2) {
                System.err.println("JSON修复失败，原始JSON: " + jsonStr);
                System.err.println("修复后JSON: " + fixedJson);
                System.err.println("修复失败原因: " + e2.getMessage());
                throw new RuntimeException("JSON解析失败，且修复尝试也失败", e);
            }
        }
    }
    
    /**
     * 修复常见的JSON格式问题
     */
    private String fixCommonJsonIssues(String jsonStr) {
        // 1. 修复中文标点符号
        jsonStr = jsonStr.replace("，", ",");
        jsonStr = jsonStr.replace("：", ":");
        jsonStr = jsonStr.replace("；", ";");
        
        // 2. 修复换行符和制表符
        jsonStr = jsonStr.replaceAll("\\r\\n", " ").replaceAll("\\n", " ").replaceAll("\\r", " ");
        jsonStr = jsonStr.replaceAll("\\t", " ");
        
        // 3. 修复缺少字段名的数组（在对象中直接出现数组）
        // 例如: {"a": 1, [{"b": 2}], "c": 3} -> {"a": 1, "data": [{"b": 2}], "c": 3}
        jsonStr = jsonStr.replaceAll(",\\s*\\[", ", \"data\": [");
        
        // 4. 修复缺少引号闭合的字符串值 - 使用更简单的方法
        jsonStr = fixUnclosedStringValuesSimple(jsonStr);
        
        // 5. 清理多余的空格
        jsonStr = jsonStr.replaceAll("\\s+", " ").trim();
        
        return jsonStr;
    }
    
    /**
     * 简单修复缺少引号闭合的字符串值
     */
    private String fixUnclosedStringValuesSimple(String jsonStr) {
        // 查找 "radar": "{ ... 的模式，在适当位置添加闭合引号
        // 使用正则表达式匹配并修复
        
        // 1. 查找 "radar": " 后面跟着的内容，直到遇到下一个字段
        String pattern = "\"radar\":\\s*\"([^\"]*?)(?=\\s*\"[a-zA-Z_][a-zA-Z0-9_]*\":)";
        java.util.regex.Pattern p = java.util.regex.Pattern.compile(pattern);
        java.util.regex.Matcher m = p.matcher(jsonStr);
        
        if (m.find()) {
            String radarContent = m.group(1);
            // 在radar内容后面添加闭合引号
            String replacement = "\"radar\": \"" + radarContent + "\"";
            jsonStr = m.replaceFirst(replacement);
        }
        
        return jsonStr;
    }

}
